package com.cykj.page04.test;

import java.lang.reflect.Field;

/**
 * @BelongsProject: HandTomcat
 * @BelongsPackage: com.cykj.page01.test
 * @Author: WWJ
 * @CreateTime: 2025-06-19 12:55
 * @Description: 通过反射获取成员属性
 * @Version: 1.0
 */
public class Lesson03 {
    public static void main(String[] args) throws Exception {
        // 1. 获取 Student 类的字节码对象
        // 使用 Class.forName 根据类名来获取该类的字节码对象（反射机制）
        Class<?> cls = Class.forName("com.cykj.page04.test.Student");

        // 2. 创建 Student 类的实例
        // 通过反射调用无参构造器来创建该类的实例
        Student o = (Student) cls.getDeclaredConstructor().newInstance();

        // 3. 获取类中所有的公有成员变量（包括父类的公有成员变量）
        // getFields() 方法会返回当前类和父类中的所有公有字段
        Field[] fields = cls.getFields();
        System.out.println("公有字段：");
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        // 4. 获取类中所有的成员变量（包括私有的、本类的成员变量）
        // getDeclaredFields() 返回当前类的所有字段（包括私有字段）
        Field[] declaredFields = cls.getDeclaredFields();
        System.out.println("所有字段（包括私有字段）：");
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }

        // 5. 获取名为 "name" 的字段
        // 使用 getDeclaredField() 方法获取指定名称的字段（不考虑父类中的字段）
        Field name = cls.getDeclaredField("name");

        // 6. 通过反射设置字段的访问权限
        // setAccessible(true) 可以绕过 Java 的访问控制检查，允许访问私有字段
        name.setAccessible(true);

        // 7. 设置 "name" 字段的值为 "李四"
        // 使用 name.set(o, "李四") 设置 Student 对象实例 o 中 "name" 字段的值
        name.set(o, "李四");

        // 8. 获取并打印 "name" 字段的值
        // 使用 name.get(o) 获取 Student 对象 o 中 "name" 字段的值
        System.out.println(name.get(o));  // 输出 "李四"
    }
}

